package javaproject;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Iterator;
import java.util.LinkedList;

public class KeyboardHandler implements KeyListener
{
    public int rotateDirection = Rotator.NONE;
    public boolean fixedRotate = false;
    private LinkedList<Integer> previousKeys;
    private Graph3D graph3D;
    private Snake snake;
    
    private boolean up_pressed;
    private boolean down_pressed;
    private boolean left_pressed;
    private boolean right_pressed;
    private boolean page_up_pressed;
    private boolean page_down_pressed;
    
    private double vx;
    private double vy;
    private double vz;
    
    private AI ai;
    KeyboardHandler(Graph3D graph3D, Snake snake, AI ai)
    {
	this.graph3D = graph3D;
	this.snake = snake;
        this.ai = ai;
        up_pressed = false;
        down_pressed = false;
        left_pressed = false;
        right_pressed = false;
        page_up_pressed = false;
        page_down_pressed = false;
        
        vx = 0;
        vy = 0;
        vz = 0;
	previousKeys = new LinkedList<Integer>();
    }
    public void keyPressed(KeyEvent e) {
	//暫停鍵
	if(e.getKeyCode() == KeyEvent.VK_SPACE)
	{
	    if(graph3D.isPaused())
 		graph3D.continueProceeding();
	    else
		graph3D.stopProceeding();
	}
        else if(e.getKeyCode() == KeyEvent.VK_Z)
	{
	    if(graph3D.isPaused())
		graph3D.shortPause();
	}
	else if(!graph3D.isPaused())
	{
	    if(previousKeys.size() < 10)
		previousKeys.add(e.getKeyCode());
	    else
	    {
		previousKeys.remove(0);
		previousKeys.add(e.getKeyCode());
	    }
	    switch(e.getKeyCode())
	    {
		//移動
		case KeyEvent.VK_UP:
                    up_pressed = true;
		    break;
		case KeyEvent.VK_DOWN:
                    down_pressed = true;
		    break;
		case KeyEvent.VK_LEFT:
                    left_pressed = true;
		    break;
		case KeyEvent.VK_RIGHT:
                    right_pressed = true;
		    break;
                    /*
		case KeyEvent.VK_PAGE_UP:
                    page_up_pressed = true;
		    graph3D.changeDirection(Snake.ASC);
		    break;
		case KeyEvent.VK_PAGE_DOWN:
                    page_down_pressed = true;
		    graph3D.changeDirection(Snake.DESC);
		    break;
                     * 
                     */

		//轉動
		case KeyEvent.VK_NUMPAD8:
		    fixedRotate = false;
		    rotateDirection = Rotator.UP;
		    break;
		case KeyEvent.VK_NUMPAD2:
		    fixedRotate = false;
		    rotateDirection = Rotator.DOWN;
		    break;
		case KeyEvent.VK_NUMPAD4:
		    fixedRotate = false;
		    rotateDirection = Rotator.LEFT;
		    break;
		case KeyEvent.VK_NUMPAD6:
		    fixedRotate = false;
		    rotateDirection = Rotator.RIGHT;
		    break;
		case KeyEvent.VK_T:
		    fixedRotate = true;
		    rotateDirection = Rotator.UP;
		    break;
		case KeyEvent.VK_G:
		    fixedRotate = true;
		    rotateDirection = Rotator.DOWN;
		    break;
		case KeyEvent.VK_F:
		    fixedRotate = true;
		    rotateDirection = Rotator.LEFT;
		    break;
		case KeyEvent.VK_H:
		    fixedRotate = true;
		    rotateDirection = Rotator.RIGHT;
		    break;

		//其他
		case KeyEvent.VK_NUMPAD1:
		    if(Config.debug)
			snake.reduce();
		    break;
		case KeyEvent.VK_NUMPAD3:
		    if(Config.debug)
			snake.add();
		    break;
		case KeyEvent.VK_NUMPAD7:
		    if(graph3D.autoRotate)
			graph3D.autoRotate = false;
		    else
			graph3D.autoRotate = true;
		    break;
	    }
            if(e.getKeyCode() == KeyEvent.VK_UP
            || e.getKeyCode() == KeyEvent.VK_DOWN
            || e.getKeyCode() == KeyEvent.VK_LEFT
            || e.getKeyCode() == KeyEvent.VK_RIGHT)
                ai.setActive(false);

            calculateVelocity();
	}
    }
    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_UP)
        {
            up_pressed = false;
        }
        if(e.getKeyCode() == KeyEvent.VK_DOWN)
        {
            down_pressed = false;
        }
        if(e.getKeyCode() == KeyEvent.VK_LEFT)
        {
            left_pressed = false;
        }
        if(e.getKeyCode() == KeyEvent.VK_RIGHT)
        {
            right_pressed = false;
        }
        /*
        if(e.getKeyCode() == KeyEvent.VK_PAGE_UP)
        {
            vz -= Config.moveZ;
            page_up_pressed = false;
        }
        if(e.getKeyCode() == KeyEvent.VK_PAGE_DOWN)
        {
            vz += Config.moveZ;
            page_down_pressed = false;
        }
         * 
         */

        if(e.getKeyCode() == KeyEvent.VK_NUMPAD8 ||
	   e.getKeyCode() == KeyEvent.VK_NUMPAD2 ||
	   e.getKeyCode() == KeyEvent.VK_NUMPAD4 ||
	   e.getKeyCode() == KeyEvent.VK_NUMPAD6)
	    rotateDirection = Rotator.NONE;
        
        if(!up_pressed && !down_pressed && !left_pressed && !right_pressed)
            ai.setActive(true);
        calculateVelocity();
    }
    private void calculateVelocity()
    {
        if(up_pressed)
            vy = Config.moveY;
        else if(down_pressed)
            vy = -Config.moveY;
        else
            vy = 0;
        if(left_pressed)
            vx = -Config.moveX;
        else if(right_pressed)
            vx = Config.moveX;
        else
            vx = 0;
        
        if(up_pressed && down_pressed)
            vy = 0;
        if(left_pressed && right_pressed)
            vx = 0;
        if(page_up_pressed && page_down_pressed)
            vz = 0;
        
        snake.setV(vx, vy, vz);
    }
    public void keyTyped(KeyEvent e) {
	//throw new UnsupportedOperationException("Not supported yet.");
    }
    public boolean checkCheat()
    {
	if(previousKeys.size() == 10)
	{
	    if(previousKeys.get(0).equals(KeyEvent.VK_UP) &&
	       previousKeys.get(1).equals(KeyEvent.VK_UP) &&
	       previousKeys.get(2).equals(KeyEvent.VK_DOWN) &&
	       previousKeys.get(3).equals(KeyEvent.VK_DOWN) &&
	       previousKeys.get(4).equals(KeyEvent.VK_LEFT) &&
	       previousKeys.get(5).equals(KeyEvent.VK_RIGHT) &&
	       previousKeys.get(6).equals(KeyEvent.VK_LEFT) &&
	       previousKeys.get(7).equals(KeyEvent.VK_RIGHT) &&
	       previousKeys.get(8).equals(KeyEvent.VK_B) &&
	       previousKeys.get(9).equals(KeyEvent.VK_A))
		return true;
	}
	return false;
    }
}
